﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.RestrictedUsage.CSharp.Compiler;
using EnvDTE;
using Microsoft.RestrictedUsage.CSharp.Core;
using Microsoft.RestrictedUsage.CSharp.Syntax;
using Microsoft.RestrictedUsage.CSharp.Semantics;
using Microsoft.VisualStudio.CSharp.Services.Language.Interop;
using Microsoft.VisualStudio.Shell.Interop;
using devtm.Documentation.HierarchyModel;
using Microsoft.RestrictedUsage.CSharp.Extensions;
using System.Collections.ObjectModel;
using devtm.Collections;
using System.Text.RegularExpressions;
using CSharpParser.Structure;
using System.IO;
using CustomTypes.Interfaces;
using CSharpParser.CSharpModel;

namespace CSharpParser
{

    public class TypeContext : IAssemblyDescriptor
    {



        private ProjectAssembly assembly;
        private DateTime lastWrite;
        private string _filename;
        private Compilation compilation;
        private Project project;


        public TypeContext(Project project)
        {

            try
            {

                if ((project != null) && !HierarchyUtilities.IsMiscellaneousProject(project))
                {

                    this.project = project;
                    _filename = project.FullName;
                }

            }
            catch
            {

            }

        }



        #region assembly

        private ProjectAssembly GetAssembly()
        {

            if (lastWrite < System.IO.File.GetLastWriteTime(_filename))
                assembly = null;

            return assembly ?? (assembly = CreateAssembly());

        }

        private ProjectAssembly CreateAssembly()
        {
            lastWrite = System.IO.File.GetLastWriteTime(_filename);
            compilation = CSharpTextSelection.LanguageModel.CreateCompiler(project).GetCompilation();
            return compilation.MainAssembly;
        }

        #endregion



        #region ITypeContext

        public string AssemblyName
        {
            get { return GetAssembly().Name.Text; }
        }

        public CustomTypes.Interfaces.Structure.ITypeStructure GetType(string @namespace, string name)
        {

            var ass = GetAssembly();

            var types = ass.Types;

            foreach (CSharpType type in types)
                if (type.Name.Text == name)
                    if (type.ContainingNamespace.GetFullNamespace() == @namespace)
                        return HierarchyParser.CreateType(type, null);

            return null;

        }

        public IEnumerable<CustomTypes.Interfaces.Structure.ITypeStructure> GetTypes(HashSet<string> namespaces)
        {

            var ass = GetAssembly();

            var types = ass.Types;

            foreach (CSharpType type in types)
            {
                string nn = type.ContainingNamespace.GetFullNamespace();

                if (namespaces == null || @namespaces.Contains(nn))
                    yield return HierarchyParser.CreateType(type, null);
            }

        }

        public void Refresh() { assembly = null; }
        public void Clear() { assembly = null; }

        #endregion



        public new TypeDescriptor GetType(string @namespace, string name)
        {
            throw new NotImplementedException();
        }

        IEnumerable<TypeDescriptor> IAssemblyDescriptor.GetTypes(HashSet<string> namespaces)
        {
            throw new NotImplementedException();
        }

        public TypeDescriptor Create(object instance)
        {
            throw new NotImplementedException();
        }
    }
}
